package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import com.sky.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.security.auth.login.LoginException;
import javax.sound.midi.MetaMessage;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private AddressBookMapper addressBookMapper;

    @Autowired
    private LoginMapper loginMapper;

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private WeChatPayUtil weChatPayUtil;

    @Autowired
    private OrderMapper orderMapper;

    @Value("${sky.shop.address}")
    private String ShopAddress;

    @Value("${sky.baidu.ak}")
    private String ak;

    @Autowired
    private WebSocketServer webSocketServer;

    private void checkAddress(String address) {
        Map map = new HashMap();
        map.put("address", ShopAddress);
        map.put("ak", ak);
        map.put("output", "json");
        String shopAddress = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3/", map);
        JSONObject object = JSONObject.parseObject(shopAddress);
        if (!object.getString("status").equals("0"))
            throw new OrderBusinessException(MessageConstant.ADDRESS_RESOLUTION_FAILED);
        JSONObject location = object.getJSONObject("result").getJSONObject("location");
        String 经度值 = location.getString("lng");
        String 纬度值 = location.getString("lat");
        String 经纬度 = 纬度值 + "," + 经度值;

        map.put("address", address);
        String addressResult = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3/", map);
        JSONObject jsonObject = JSONObject.parseObject(addressResult);
        if (!jsonObject.getString("status").equals("0"))
            throw new OrderBusinessException(MessageConstant.ADDRESS_RESOLUTION_FAILED);
        JSONObject jsonObject1 = jsonObject.getJSONObject("result").getJSONObject("location");
        String addAddress经度值 = jsonObject1.getString("lng");
        String addAddress纬度值 = jsonObject1.getString("lat");
        String addAddress经纬度 = addAddress纬度值 + "," + addAddress经度值;

        Map rule = new HashMap();
        rule.put("origin", 经纬度);
        rule.put("destination", addAddress经纬度);
        rule.put("ak", ak);

        String str = HttpClientUtil.doGet("https://api.map.baidu.com/direction/v2/riding", rule);
        JSONObject parseObject = JSONObject.parseObject(str);
        log.info("parseObject:{}", parseObject);
        if (!parseObject.getString("status").equals("0"))
            throw new OrderBusinessException(parseObject.getString("message"));
        String distance = parseObject.getJSONObject("result").getJSONArray("routes").getJSONObject(0).getString("distance");
        int distanceInt = Integer.parseInt(distance);
        if (distanceInt > 50000) throw new OrderBusinessException(MessageConstant.OUT_OF_DELIVERY);

    }


    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        AddressBook addressBookById = addressBookMapper.getAddressBookById(ordersSubmitDTO.getAddressBookId());
        if (addressBookById == null) throw new OrderBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);

        log.info("买家地址:{}", addressBookById.getDetail());
        checkAddress(addressBookById.getDetail());

        User user = loginMapper.selectById(BaseContext.getCurrentId());
        if (user == null) throw new OrderBusinessException(MessageConstant.USER_NOT_LOGIN);

        List<ShoppingCart> list = shoppingCartMapper.list(BaseContext.getCurrentId());
        if (list == null) throw new OrderBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);

        Orders orders = Orders.builder().number(UUID.randomUUID().toString().replace("-", "").substring(0, 15)).status(Orders.PENDING_PAYMENT).userId(BaseContext.getCurrentId()).orderTime(LocalDateTime.now()).payStatus(Orders.UN_PAID).phone(addressBookById.getPhone()).address(addressBookById.getDetail()).userName(user.getName()).consignee(addressBookById.getConsignee()).build();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orderMapper.insert(orders);

        List<OrderDetail> orderDetails = new ArrayList<>();
        list.forEach(cart -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(cart, orderDetail, "id");
            orderDetail.setOrderId(orders.getId());
            orderDetails.add(orderDetail);
        });

        orderDetailMapper.insertBatch(orderDetails);

        shoppingCartMapper.clean(BaseContext.getCurrentId());

        return OrderSubmitVO.builder().id(orders.getId()).orderNumber(orders.getNumber()).orderAmount(orders.getAmount()).orderTime(orders.getOrderTime()).build();
    }

    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        User user = loginMapper.selectById(userId);

        //调用微信支付接口，生成预支付交易单
        JSONObject jsonObject = weChatPayUtil.pay(ordersPaymentDTO.getOrderNumber(), //商户订单号
                new BigDecimal(0.01), //支付金额，单位 元
                "苍穹外卖订单", //商品描述
                user.getOpenid() //微信用户的openid
        );

        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
            throw new OrderBusinessException("该订单已支付");
        }

        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));

        paySuccess(ordersPaymentDTO.getOrderNumber());
        return new OrderPaymentVO();
    }

    public void paySuccess(String outTradeNo) {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单号查询当前用户的订单
        Orders ordersDB = orderMapper.getByNumberAndUserId(outTradeNo, userId);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder().id(ordersDB.getId()).status(Orders.TO_BE_CONFIRMED).payStatus(Orders.PAID).checkoutTime(LocalDateTime.now()).build();

        orderMapper.update(orders);

        Map map = new HashMap();
        map.put("type", 1);
        map.put("orderId", ordersDB.getId());
        map.put("content", "订单号: " + outTradeNo);
        webSocketServer.sendToAllClient(JSONObject.toJSONString(map));

    }

    @Override
    public PageResult getHistoryOrders(OrdersPageQueryDTO ordersPageQueryDTO) {

        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        Page<OrderVO> p = (Page<OrderVO>) orderMapper.getHistoryOrders(BaseContext.getCurrentId(), ordersPageQueryDTO.getStatus());

        for (OrderVO orderVO : p) {
            Long id = orderVO.getId();
            List<OrderDetail> orders = orderDetailMapper.getHistoryOrders(id);
            orderVO.setOrderDetailList(orders);
        }

        return new PageResult(p.getTotal(), p.getResult());
    }

    @Override
    public OrderVO getOrderDetail(Long id) {
        OrderVO orderVO = orderMapper.getOrderDetail(id);
        List<OrderDetail> orders = orderDetailMapper.getHistoryOrders(id);
        orderVO.setOrderDetailList(orders);
        return orderVO;
    }

    @Override
    public void cancel(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelTime(LocalDateTime.now());
        orders.setCancelReason("用户取消");
        orderMapper.cancel(orders);
    }

    @Override
    public void getRepetition(Long id) {
        List<OrderDetail> orders = orderDetailMapper.getHistoryOrders(id);
        List<ShoppingCart> list = orders.stream().map(new Function<OrderDetail, ShoppingCart>() {
            @Override
            public ShoppingCart apply(OrderDetail orderDetail) {
                ShoppingCart shoppingCart = new ShoppingCart();

                BeanUtils.copyProperties(orderDetail, shoppingCart, "id");
                shoppingCart.setUserId(BaseContext.getCurrentId());
                shoppingCart.setCreateTime(LocalDateTime.now());
                return shoppingCart;
            }
        }).toList();
        shoppingCartMapper.insertBatch(list);

    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        Page<OrderVO> p = (Page<OrderVO>) orderMapper.conditionSearch(
                ordersPageQueryDTO.getBeginTime(),
                ordersPageQueryDTO.getEndTime(),
                ordersPageQueryDTO.getNumber(),
                ordersPageQueryDTO.getPhone(),
                ordersPageQueryDTO.getStatus()
        );

        return new PageResult(p.getTotal(), p.getResult());
    }

    @Override
    public OrderStatisticsVO statistics() {
        return OrderStatisticsVO.builder().toBeConfirmed(orderMapper.countToBeConfirmed(Orders.TO_BE_CONFIRMED)).confirmed(orderMapper.countToBeConfirmed(Orders.CONFIRMED)).deliveryInProgress(orderMapper.countToBeConfirmed(Orders.DELIVERY_IN_PROGRESS)).build();
    }

    @Override
    public OrderVO details(Long id) {
        OrderVO detail = orderMapper.getOrderDetail(id);

        List<OrderDetail> orders = orderDetailMapper.getHistoryOrders(detail.getId());
        detail.setOrderDetailList(orders);
        return detail;
    }

    @Override
    public void confirm(OrdersConfirmDTO orders) {
        orders.setStatus(Orders.CONFIRMED);
        orderMapper.confirm(orders);
    }

    @Override
    public void rejection(OrdersRejectionDTO orders) {

        Orders detail = orderMapper.getOrderDetail(orders.getId());
        if (detail == null || !detail.getStatus().equals(Orders.TO_BE_CONFIRMED))
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);

        Orders order = new Orders();
        order.setStatus(Orders.CANCELLED);
        order.setCancelTime(LocalDateTime.now());
        BeanUtils.copyProperties(orders, order);

        orderMapper.rejection(order);
    }

    @Override
    public void updateCancel(OrdersCancelDTO orders) {
        Orders order = Orders.builder().status(Orders.CANCELLED).build();
        BeanUtils.copyProperties(orders, order);
        orderMapper.updateCancel(order);
    }

    @Override
    public void delivery(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        orderMapper.delivery(orders);
    }

    @Override
    public void complete(Long id) {
        Orders orders = Orders.builder().status(Orders.COMPLETED).id(id).deliveryTime(LocalDateTime.now()).build();
        orderMapper.complete(orders);
    }

    @Override
    public void getReminder(Long id) {

        OrderVO detail = orderMapper.getOrderDetail(id);
        if (detail == null) throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);

        Map map = new HashMap();
        map.put("type", 2);
        map.put("orderId", detail.getId());
        map.put("content", "订单号: " + detail.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }
}
